#include <iostream>

class Base
{
public:
    // 多态：同一个函数呈现出不同的功能
    // 虚函数实现动多态
    // 调用的时候定死是基类的指针后，就只能找到基类的代码段，只能调到基类的函数
    // 靠虚函数指针才能调到子类的函数
    virtual void show()
    {
        std::cout<<"Base"<<std::endl;
    }
protected:
    int a;
};
// 实现过程：加了virtusl关键字之后，在基类中会有一个虚函数指针vptr,它指向一个Base的表，里面有个虚函数show
// 其子类里面也会有一个虚函数指针vptr，指向它自己的一张表，没实现自己的show函数的时候，表里存的就是父类的show函数地址，当实现了自己的show函数的时候，表里存的就是自己的show函数地址
// 虚函数指针就直接占用其内存空间，指向要调用的函数
class Derived1:public Base
{
public:
    void show()
    {
        std::cout<<"Derived1"<<std::endl;
    }
};

class Derived2:public Base
{
public:
    void show()
    {
        std::cout<<"Derived2"<<std::endl;
    }
};

int main()
{
#if 0
    // 向上转型：将一个子类的对象给到了一个基类的指针（必须有继承关系）
    Derived1 *d = new Derived1;  // 用基类的指针指向了子类的对象（跟指针走）
    Base *b = d;
    b->show();
    d->show();
    // b和d实际上指向的是同一个位置，但是调用的函数不一样
    // 基类指针会调基类函数，子类指针会调子类函数
#endif

#if 1
    // 这样写，它俩之间没有任何关系
    // Derived1 *d1 = new Derived1;
    // Derived2 *d2 = new Derived2;

    // 通过向上转型，它们就融合成相同的指针类型
    // Base *d1 = new Derived1;
    // Base *d2 = new Derived2;

    // 可以把它们放在一个数组里面
    // 这样就实现了，把不同类的对象，由同一个类型的数组去统一管理
    Base *a[2];
    a[0] = new Derived1;
    a[1] = new Derived2;
    for(int i = 0; i < 2; i++)
    {
        a[i]->show();
    }
    return 0;
    // 这样就可以统一地管理各种不同的对象
    // 但是这样管理有个问题，由于基类指针只能调基类的函数，这就导致，虽然是不同的对象，但由于向上转型都变成了同一个父类的指针，调的还是父类的函数
    // 这样就失去了构建不同对象的意义，不能实现不同show函数所带来的不同的功能
    // 希望的是呈现不同的功能又能统一管理
    // 给父类的show函数加个virtual，这样一来就能实现需求
    // 这就是多态
#endif
}